package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.FaceTemplate;
<<<<<<< HEAD
=======
import com.tanhua.commons.templates.HuanXinTemplate;
>>>>>>> acc7004 (第4天到第8天)
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.db.User;
import com.tanhua.db.UserInfo;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.GetAgeUtil;
import com.tanhua.server.utils.JwtUtils;
import com.tanhua.vo.ErrorResult;
import com.tanhua.vo.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @version 1.0
 * @author： xtr
 * @date： 2021-03-04 21:26
 */
@Service
@Slf4j //打日志
public class UserService {

    @Reference
    private UserApi userApi;

    @Value("${tanhua.redisValidateCodeKeyPrefix}")
    private String redisValidateCodeKeyPrefix;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private JwtUtils jwtUtils;

    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private FaceTemplate faceTemplate;

    @Autowired
    private OssTemplate ossTemplate;
<<<<<<< HEAD
=======

    @Autowired
    private HuanXinTemplate huanXinTemplate;
>>>>>>> acc7004 (第4天到第8天)
    /**
     * 根据手机号查询用户
     * @param mobile
     * @return
     */
    public ResponseEntity findUserByMobile(String mobile) {
        User user = userApi.findByMobile(mobile);
        return ResponseEntity.ok(user);
    }

    /**
     * 新增用户
     * @param mobile
     * @param password
     */
    public ResponseEntity save(String mobile, String password) {
        User user = new User();
        user.setMobile(mobile);
        user.setPassword(password);
        userApi.save(user);
        return ResponseEntity.ok(null);
    }

    /**
     * 发送验证码
     * @param phone
     */
    public void sendValidateCode(String phone) {
        // 1. 获取redis中存入的验证码key
        String key = redisValidateCodeKeyPrefix+phone;
        // 2. redis中的验证码
        String CodeInRedis = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotEmpty(CodeInRedis)){
            //如果redis中存在验证码，则说明验证码还未过期
            throw new TanHuaException(ErrorResult.duplicate());
        }
        // 4. 生成验证码
        String validateCode = RandomStringUtils.randomNumeric(6);
        // 5. 发送验证码
        log.debug("发送验证码：{},{}",phone,validateCode);
        //Map<String, String> smsRs = smsTemplate.sendValidateCode(phone, validateCode);
        //if (smsRs!=null){
        //    //验证码发送失败
        //    throw new TanHuaException(ErrorResult.fail());
        //}
        // 6. 将验证码存入redis，有效期五分钟
        log.info("将验证码存入redis");
        redisTemplate.opsForValue().set(key,validateCode,5, TimeUnit.MINUTES);
    }

    /**
     * 登录或注册,校验验证码
     * @param phone
     * @param verificationCode
     * @return
     */
    public Map<String, Object> loginVerification(String phone, String verificationCode) {
        // redis 中存入的key
        String key = redisValidateCodeKeyPrefix + phone;

        //redis 中的验证码
        String codeInRedis = redisTemplate.opsForValue().get(key);

        log.debug("========== 校验 验证码:{},{},{}",phone,codeInRedis,verificationCode);
        if (StringUtils.isEmpty(codeInRedis)){
            //
            throw new TanHuaException(ErrorResult.loginError());
        }
        if (!codeInRedis.equals(verificationCode)){
            //验证码错误
            throw new TanHuaException(ErrorResult.validateCodeError());
        }
        // 防止重复提交
        redisTemplate.delete(key);
        //查看用户是否存在
        User user = userApi.findByMobile(phone);
        boolean isNew = false;
        if (user == null){
            //用户不存在则注册
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5DigestAsHex(phone.substring(phone.length()-6).getBytes(StandardCharsets.UTF_8)));
            log.info("=============添加新用户 {}"+phone);
            Long id = userApi.save(user);
            user.setId(id);
            isNew = true;
<<<<<<< HEAD
=======



            // 注册环信, 默认密码为123456
            huanXinTemplate.register(id);



>>>>>>> acc7004 (第4天到第8天)
        }
        //签发token令牌
        String token = jwtUtils.createJWT(phone, user.getId());
        //用户信息存入redis，方便后期获取，有效期为3天
        String userString = JSON.toJSONString(user);
        redisTemplate.opsForValue().set("TOKEN_"+token,userString,3,TimeUnit.DAYS);
        log.debug("===========签发的token: {}" ,token);
        //返回结果
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);
        return resultMap;
    }

    /**
     * 通过token获取用户信息
     * @param token
     * @return
     */
    public User getUserByToken(String token){
        //定义redis中的token的key值
        String key = "TOKEN_"+token;
        //通过key获取用户信息字符串,用户信息是以字符串的形式存到redis中的
        String userString = redisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(userString)){
            return null;
        }
        //存在则重新设置用户token的有效期，即延长
        redisTemplate.expire(key,7,TimeUnit.DAYS);
        //转换成对象形式
        User user = JSON.parseObject(userString, User.class);
        return user;
    }

    /**
     * 保存用户信息
     * 新用户---1填写资料
     * @param userInfo
     * @param token
     */
    public void saveUserInfo(UserInfo userInfo, String token) {
        //根据token获取用户信息
//        User user = getUserByToken(token);
//        if (user == null){
//            //如果为空，则报错，token失效
//            throw new TanHuaException("登录超时，请重新登录");
//        }

        //拦截器token统一处理
        userInfo.setId(UserHolder.getUserId());
        userInfo.setAge(GetAgeUtil.getAge(userInfo.getBirthday()));
        userInfoApi.save(userInfo);
    }

    /**
     * 用户上传图片
     * @param token
     * @param headPhoto
     */
    public void uploadAvatar(String token, MultipartFile headPhoto) {
//        User user = getUserByToken(token);
//        if (user == null){
//            throw new TanHuaException("登录超时，请重新登陆");
//        }

        //拦截器token统一处理
        //人脸检测
        try {
            byte[]  photoBytes = headPhoto.getBytes();
            if (!faceTemplate.detect(photoBytes)){
                throw new TanHuaException("没有检测到人脸，请重新上传");
            }
            //检测通过,则上传oss
            //获取文件名
            String filename = headPhoto.getOriginalFilename();
            //获取输入流
            InputStream ris = headPhoto.getInputStream();
            //上传
            String avatar = ossTemplate.upload(filename, ris);
            //设置属性
            UserInfo userInfo = new UserInfo();
            userInfo.setId(UserHolder.getUserId());
            userInfo.setAvatar(avatar);
            //更新头像保存
            userInfoApi.update(userInfo);
        } catch (IOException e) {
            log.error("上传文件失败");
            throw new TanHuaException("上传头像失败，请稍后重试");
        }

    }

    /**
     * 通过id查询用户
     * 用户资料 - 读取
     * @param id
     * @return
     */
    public UserInfoVo findUserInfoById(Long id) {
        UserInfo userInfo = userInfoApi.findUserInfoById(id);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo,userInfoVo);
        Integer age = userInfo.getAge();
        if (age == null){
            userInfoVo.setAge("18");
        }else {
            userInfoVo.setAge(age.toString());
        }
        return userInfoVo;
    }

    /**
     * 更新用户信息
     * @param token
     * @param userInfoVo
     */
    public void updateUserInfo(String token, UserInfoVo userInfoVo) {
        log.info("开始更新用户信息");
//        User user = getUserByToken(token);
//        if (user == null){
//            throw new TanHuaException("登录超时，请重新登陆");
//        }

        //拦截器token统一处理
        UserInfo userInfo = new UserInfo();
        //从userInfoVo将数据复制到userInfo，相同字段的复制
        BeanUtils.copyProperties(userInfoVo,userInfo);
        userInfo.setId(UserHolder.getUserId());
        userInfo.setAge(GetAgeUtil.getAge(userInfoVo.getBirthday()));
        userInfoApi.update(userInfo);
        log.info("更新用户信息成功..........{}",userInfo);
    }

    /**
     * 更新用户头像
     * @param token
     * @param headPhoto
     */
    public void updateHeaderImage(String token, MultipartFile headPhoto) {
        log.info("开始更新头像..............");
//        User user = getUserByToken(token);
//        if (user == null){
//            throw new TanHuaException("登录失效，请重新登陆");
//        }

        //拦截器token统一处理
        //查询用户信息，用于后期删除阿里上老的头像信息

        UserInfo userinfo = userInfoApi.findUserInfoById(UserHolder.getUserId());
        String oldAvatar = userinfo.getAvatar();
        try {
            byte[] bytes = headPhoto.getBytes();
            if (!faceTemplate.detect(bytes)){
                throw new TanHuaException("没有检测到人脸，请重新上传");
            }
            //人脸识别通过
            //上传到oss
            //获取文件名
            String filename = headPhoto.getOriginalFilename();
            String photoUrl = ossTemplate.upload(filename, headPhoto.getInputStream());
            UserInfo userInfo = new UserInfo();
            //根据id更新，只改变头像
            userInfo.setId(UserHolder.getUserId());
            userInfo.setAvatar(photoUrl);
            userInfoApi.update(userInfo);
            log.info("头像更新成功...............");
            //删除旧的头像
            ossTemplate.deleteFile(oldAvatar);
        } catch (IOException e) {
            throw new TanHuaException("上传头像失败，请稍后重试");
        }
    }
}
